﻿using System.Diagnostics;
using System.Reflection;
using DryIoc;


namespace KinonekoSoftware.Studio.ViewModels
{

    public sealed partial class StartupViewModel : TabViewModel
    {
        private readonly List<JuXiaoYouLaunchJob> _LaunchRuners;
        private          string                   _description;

        public StartupViewModel()
        {
            _LaunchRuners = new List<JuXiaoYouLaunchJob>(8);

            //
            //
            CreateJob(SR.Title_Loading_Setting, LaunchJOB_Step1_LoadSetting);
            CreateJob(SR.Title_Repository_Loading, LaunchJOB_Step2_LoadRepo);
            CreateJob(SR.Title_Loading_FinalOperation, LaunchJOB_Step3_GetArchInfo);
            Title = SR.App_Launch;
        }

        private void CreateJob(string desc, JuXiaoYouLaunchJobHandler handler)
        {
            _LaunchRuners.Add(new JuXiaoYouLaunchJob
            {

                Description = desc,
                Handler     = handler,
            });
        }

        private async Task LaunchJOB_Step1_LoadSetting(AppViewModel app, IContainer container, JuXiaoYouLaunchContext context)
        {
            var sw            = new Stopwatch();
            var ai            = container.Resolve<ApplicationInformation>();
            var setting       = Path.Combine(ai.SettingFolder, Platform.FileName_Setting_Repo);
            var studioSetting = Path.Combine(ai.SettingFolder, Platform.FileName_Setting_App);

            sw.Start();
            var repo = await JSON.FileAsync<RepositorySetting>(setting, () => new RepositorySetting
            {
                Repositories   = new List<RepositoryCache>(),
                LastRepository = null,
            }, false);

            var studio = await JSON.FileAsync<JuXiaoYouSetting>(studioSetting, () => new JuXiaoYouSetting
            {
                DataMode = DataMode.Release,
            }, false);

            Ioc.Use<RepositorySetting>(repo);
            Ioc.Use<JuXiaoYouSetting>(studio);

            context.RepositorySetting = repo;
            context.JuXiaoYouSetting  = studio;
            sw.Stop();

            Xplat.Debug($"加载设置耗时:{sw.ElapsedMilliseconds}ms");
            Xplat.RunOnUIThread(() =>
            {
                PushToView("1");
                Ioc.Get<AppViewModel>().InitializeTimeService();
            });
        }


        private async Task LaunchJOB_Step2_LoadRepo(AppViewModel app, IContainer container, JuXiaoYouLaunchContext context)
        {
            long freeBytes  = 0;
            long usageBytes = 0;


            if (context.RepositorySetting is null)
            {
                return;
            }


            Xplat.RunOnUIThread(() =>
            {
                app.RepositoryHashSet.Clear();
                app.Repositories.Clear();
                foreach (var repository in context.RepositorySetting.Repositories)
                {
                    app.RepositoryHashSet.Add(repository.Path);
                    app.Repositories.Add(repository);
                }
            });

            //
            // 加载世界观
            if (!string.IsNullOrEmpty(context.RepositorySetting.LastRepository))
            {
                //
                //
                var runtime = Ioc.Get<RepositoryRuntime>();

                var r = await runtime.LoadAsync(context.RepositorySetting.LastRepository, context.JuXiaoYouSetting
                                                                                                 .DataMode);

                // freeBytes  = ((Repository)runtime.Repository).FreeBytes;
                // usageBytes = ((Repository)runtime.Repository).UsageBytes;

                //
                // 输出耗时
                runtime.Diagnostic();

                //
                //
                context.IsLoaded = r.IsFinished;

                if (!r.IsFinished)
                {
                    //
                    //
                    context.RepositorySetting.LastRepository = null;

                    //
                    //
                    await Warning(TitleSR.WarningOperation, r.Reason);
                }
            }

            // Xplat.Debug($"加载世界观耗时:{sw.ElapsedMilliseconds}ms，数据库已用大小: {usageBytes} Byte,  数据库可用大小: {freeBytes} Byte");
        }

        private static Task LaunchJOB_Step3_GetArchInfo(AppViewModel app, IContainer container, JuXiaoYouLaunchContext context)
        {
            return Task.Run(() =>
            {

                var assembly     = typeof(StartupViewModel).Assembly;
                var archVer      = assembly.GetCustomAttribute<ArchitectureVersionAttribute>();
                var appVer       = assembly.GetCustomAttribute<ApplicationVersionAttribute>();
                var appInsideVer = assembly.GetCustomAttribute<ApplicationInsideVersionAttribute>();

                context.ArchitectureVersion      = archVer?.Version;
                context.ApplicationVersion       = appVer?.Version;
                context.Major                    = appVer?.Major       ?? 3;
                context.Minor                    = appVer?.Minor       ?? 6;
                context.BuildNumber              = appVer?.BuildNumber ?? 0;
                context.Revision                 = appVer?.Revision    ?? 0;
                context.ApplicationInsideVersion = appInsideVer?.Version;
                
                //
                //
                (Ioc.Get<ShellCore>() as AppViewModel)?.CheckUpdate(); 

                System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(context.ApplicationVersion));
                System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(context.ArchitectureVersion));
            });
        }

        protected override void OnStart()
        {
            //
            //
            Xplat.RunOnUIThread(() => Description = _LaunchRuners.FirstOrDefault()?.Description);

            //
            // 执行启动任务
            Task.Run(async () =>
            {
                var app = Ioc.Get<AppViewModel>();

                foreach (var runner in _LaunchRuners)
                {
                    Xplat.RunOnUIThread(() => Description = runner.Description);
                    await runner.Run();
                }

                Xplat.RunOnUIThread(() =>
                {
                    //
                    // 完成了所有加载操作
                    if (!app.IsLoaded)
                    {
                        //
                        // 直接跳转到Creation
                        GoTo<RepositoryCreationViewModel>();
                    }
                    else
                    {
                        //
                        // 直接跳转到Home
                        GoTo<RepositoryGalleryViewModel>();

                        //
                        //
                        Debug();
                    }

                    //
                    // 设置已经加载
                    app.LaunchContext.IsLaunch = true;
                });


                await Close(this);
            });

            base.OnStart();
        }


        /// <summary>
        /// 获取或设置 <see cref="Description"/> 属性。
        /// </summary>
        public string Description
        {
            get => _description;
            set => SetValue(ref _description, value);
        }
    }
}